package vip.xiaonuo.issued.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.httpclient.ReturnJson;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.param.DeviceBaseParam;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.deviceset.entity.DwDeviceSet;
import vip.xiaonuo.facedoor.modular.deviceset.service.DwDeviceSetService;
import vip.xiaonuo.facedoor.modular.memberdevice.entity.MemberDevice;
import vip.xiaonuo.facedoor.modular.memberdevice.service.MemberDeviceService;
import vip.xiaonuo.facedoor.modular.orgdevice.entity.OrgDevice;
import vip.xiaonuo.facedoor.modular.orgdevice.service.OrgDeviceService;
import vip.xiaonuo.facedoor.modular.visitordevice.entity.VisitorDevice;
import vip.xiaonuo.facedoor.modular.visitordevice.service.VisitorDeviceService;
import vip.xiaonuo.facedoor.iservice.IDeviceBaseService;
import vip.xiaonuo.facedoor.iservice.IFaceDoorDtoService;
import vip.xiaonuo.facedoor.rule.HQRulesEngine;
import vip.xiaonuo.facedoor.rule.RuleConstant;
import vip.xiaonuo.facedoor.vo.dewo.DeletePersonRequest;
import vip.xiaonuo.facedoor.vo.dewo.GetPersonRequest;
import vip.xiaonuo.facedoor.vo.dewo.GetPersonResponse;
import vip.xiaonuo.facedoor.vo.haiqing.*;
import vip.xiaonuo.sys.modular.timer.param.SysTimersParam;
import vip.xiaonuo.sys.modular.timer.service.SysTimersService;

import java.util.Calendar;
import java.util.Optional;

@Service(value = RuleConstant.HQ + RuleConstant.DEVICE_BASE)
@Slf4j
public class HQHttpDeviceBaseService implements IDeviceBaseService {


    @Autowired
    private OrgDeviceService orgDeviceService;

    @Autowired
    private MemberDeviceService memberDeviceService;

    @Autowired
    private SysTimersService sysTimersService;

    @Autowired
    private VisitorDeviceService visitorDeviceService;

    @Autowired
    private DeviceBaseService deviceBaseService;

    @Autowired
    private DwDeviceSetService dwDeviceSetService;

    @Override
    public PageResult<GetPersonResponse.DataDTO.PersonnelListDTO> listPerson(Long deviceId,String name) {
        DeviceBase deviceBase = deviceBaseService.getById(deviceId);
        if (StringUtils.isEmpty(deviceBase.getCabinetIp()) || deviceBase.getCabinetPort() == null) {
            throw new ServiceException(500, "设备尚未配置ip和端口!");
        }
        String uri = IFaceDoorDtoService.getBaseParam(deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));
        Page<GetPersonResponse.DataDTO.PersonnelListDTO> objectPage = PageFactory.defaultPage();
        long current = objectPage.getCurrent();
        objectPage.setSize(10);
        GetPersonRequest getPersonRequest =
                new GetPersonRequest().setPage(current + "").setLimit(10 + "");
        try {
            GetPersonResponse getPersonResponse = HQRulesEngine.faceDoorDtoService.listPerson(uri, getPersonRequest);
            objectPage.setTotal(Long.parseLong(getPersonResponse.getData().getTotalNum()));
            return new PageResult<>(objectPage, getPersonResponse.getData().getPersonnelList());
        } catch (Exception e) {
            throw new ServiceException(500, "获取人员信息发生错误 错误信息【" + ExceptionUtils.getMessage(e) + "】");
        }
    }

    @Override
    public void delete(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(deviceBaseParam.getId());
        // 强制删除 不清空设备人员
        if ((deviceBase.getCabinetIp() == null || deviceBase.getCabinetPort() == null) || (deviceBaseParam.getMandatory() != null && ObjectUtil.equal(deviceBaseParam.getMandatory(), 1))) {
            deviceBaseService.removeById(deviceBaseParam.getId());
            orgDeviceService.remove(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getDeviceId, deviceBase.getId()));
            memberDeviceService.remove(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getDeviceId, deviceBase.getId()));
            visitorDeviceService.remove(new LambdaQueryWrapper<VisitorDevice>().eq(VisitorDevice::getDeviceId, deviceBase.getId()));
            dwDeviceSetService.remove(new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceBaseId,deviceBase.getId()));
            // 定时任务删除
            SysTimersParam sysTimersParam = new SysTimersParam();
            sysTimersParam.setId(deviceBase.getTaskId());
            sysTimersService.delete(sysTimersParam);
            return;
        }
        String password = Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin");
        RequestHeader requestHeader = new RequestHeader().setUserName("admin").setPassWord(password);
        String uri = IFaceDoorDtoService.getBaseParam(deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));
        DeletePersonRequest deletePersonRequest = new DeletePersonRequest();
        deletePersonRequest.setRequestHeader(requestHeader);
        try {
            ReturnJson returnJson = HQRulesEngine.faceDoorDtoService.deleteAllPerson(uri, deletePersonRequest);
            if (ObjectUtil.equal("0000",returnJson.getCode()) ) {
                deviceBaseService.removeById(deviceBaseParam.getId());
                orgDeviceService.remove(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getDeviceId, deviceBase.getId()));
                memberDeviceService.remove(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getDeviceId, deviceBase.getId()));
                visitorDeviceService.remove(new LambdaQueryWrapper<VisitorDevice>().eq(VisitorDevice::getDeviceId, deviceBase.getId()));
                dwDeviceSetService.remove(new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceBaseId,deviceBase.getId()));
                // 定时任务删除
                SysTimersParam sysTimersParam = new SysTimersParam();
                sysTimersParam.setId(deviceBase.getTaskId());
                sysTimersService.delete(sysTimersParam);
            } else {
                throw new ServiceException(500,
                        "删除设备失败 失败信息： code"
                                + returnJson.getCode()
                                + " message"
                                + Optional.ofNullable(returnJson.getMsg()).orElse(""));
            }
        } catch (Exception e) {
            throw new ServiceException(500, "删除设备失败 失败信息：" + ExceptionUtil.getMessage(e));
        }
    }

    @Override
    public void setUserPwd(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = getDeviceBase(deviceBaseParam);
        String uri = IFaceDoorDtoService.getBaseParam(
                deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));
        try {
            SetUserPwdRequest baseRequest = new SetUserPwdRequest();
            RequestHeader requestHeader = new RequestHeader();
            requestHeader
                    .setUserName(
                            Optional.ofNullable(deviceBase.getDeviceLoginName()).orElse("admin"))
                    .setPassWord(
                            Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin"));
            SetUserPwdRequest.InfoDTO infoDTO = new SetUserPwdRequest.InfoDTO();
            infoDTO.setUser(deviceBaseParam.getDeviceLoginName());
            infoDTO.setPwd(deviceBaseParam.getDevicePassword());
            baseRequest.setInfo(infoDTO);
            BaseResponse baseResponse = HQRulesEngine.faceDoorDtoService.setUserPwd(uri, baseRequest, requestHeader);
            if (ObjectUtil.equal(baseResponse.getCode(), 200)) {
                deviceBase.setDevicePassword(deviceBaseParam.getDevicePassword());
                deviceBase.setDeviceLoginName(deviceBaseParam.getDeviceLoginName());
                deviceBaseService.updateById(deviceBase);
            } else {
                throw new ServiceException(
                        500,
                        "设置用户名密码 失败信息： code:"
                                + baseResponse.getCode()
                                + " message:  "
                                + Optional.ofNullable(baseResponse.getInfo().getResult())
                                        .orElse("")
                                + " "
                                + Optional.ofNullable(baseResponse.getInfo().getDetail())
                                        .orElse(""));
            }
        } catch (Exception e) {
            throw new ServiceException(500, "设置用户名密码 失败信息：" + ExceptionUtil.getMessage(e));
        }
    }

    @Override
    public void setFactoryDefault(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = getDeviceBase(deviceBaseParam);
        String uri = IFaceDoorDtoService.getBaseParam(
                deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));

        try {
            SetFactoryDefaultRequest setFactoryDefaultRequest = new SetFactoryDefaultRequest();
            RequestHeader requestHeader = new RequestHeader();
            requestHeader
                    .setUserName(
                            Optional.ofNullable(deviceBase.getDeviceLoginName()).orElse("admin"))
                    .setPassWord(
                            Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin"));
            SetFactoryDefaultRequest.InfoDTO infoDTO = new SetFactoryDefaultRequest.InfoDTO();
            BeanUtils.copyProperties(deviceBaseParam, infoDTO);
            setFactoryDefaultRequest.setInfo(infoDTO);
            BaseResponse baseResponse =
                    HQRulesEngine.faceDoorDtoService.setFactoryDefault(uri, setFactoryDefaultRequest, requestHeader);
            if (ObjectUtil.equal(baseResponse.getCode(), 200)) {
                log.info("恢复出场设置成功 设备将要重启！");
            } else {
                throw new ServiceException(
                        500,
                        "恢复出场设置 失败信息： code:"
                                + baseResponse.getCode()
                                + " message:  "
                                + Optional.ofNullable(baseResponse.getInfo().getResult())
                                        .orElse("")
                                + " "
                                + Optional.ofNullable(baseResponse.getInfo().getDetail())
                                        .orElse(""));
            }
        } catch (Exception e) {
            throw new ServiceException(500, "恢复出场设置 失败信息：" + ExceptionUtil.getMessage(e));
        }
    }

    @NotNull
    private DeviceBase getDeviceBase(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(deviceBaseParam.getId());
        if (deviceBase == null) {
            throw new ServiceException(500, "找不到该设备!");
        }
        if (StringUtils.isEmpty(deviceBase.getCabinetIp()) || deviceBase.getCabinetPort() == null) {
            throw new ServiceException(500, "设备尚未配置ip和端口!");
        }
        return deviceBase;
    }

    @Override
    public void setSysTime(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = getDeviceBase(deviceBaseParam);
        String uri = IFaceDoorDtoService.getBaseParam(
                deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));
        try {
            RequestHeader requestHeader = new RequestHeader()
                    .setUserName(
                            Optional.ofNullable(deviceBase.getDeviceLoginName()).orElse("admin"))
                    .setPassWord(
                            Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin"));

            Calendar instance = Calendar.getInstance();
            SetSysTimeRequest.InfoDTO infoDTO = new SetSysTimeRequest.InfoDTO()
                    .setYear(instance.get(Calendar.YEAR))
                    .setMonth(instance.get(Calendar.MONTH) + 1)
                    .setDay(Calendar.getInstance().get(Calendar.DATE))
                    .setHour(instance.get(Calendar.HOUR_OF_DAY))
                    .setMinute(instance.get(Calendar.MINUTE))
                    .setSecond(instance.get(Calendar.SECOND));

            SetSysTimeRequest setSysTimeRequest = new SetSysTimeRequest();
            setSysTimeRequest.setInfo(infoDTO);
            BaseResponse baseResponse =
                    HQRulesEngine.faceDoorDtoService.setSysTime(uri, setSysTimeRequest, requestHeader);
            if (ObjectUtil.equal(baseResponse.getCode(), 200)) {
                log.info("设备时间设置成功！");
            } else {
                throw new ServiceException(
                        500,
                        "设备时间设置 失败信息： code:"
                                + baseResponse.getCode()
                                + " message:  "
                                + Optional.ofNullable(baseResponse.getInfo().getResult())
                                        .orElse("")
                                + " "
                                + Optional.ofNullable(baseResponse.getInfo().getDetail())
                                        .orElse(""));
            }
        } catch (Exception e) {
            throw new ServiceException(500, "设备时间设置 失败信息：" + ExceptionUtil.getMessage(e));
        }
    }

    @Override
    public void openDoor(DeviceBaseParam deviceBaseParam) {
        DeviceBase deviceBase = getDeviceBase(deviceBaseParam);
        String uri = IFaceDoorDtoService.getBaseParam(
                deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));
        try {
            RequestHeader requestHeader = new RequestHeader()
                    .setUserName(
                            Optional.ofNullable(deviceBase.getDeviceLoginName()).orElse("admin"))
                    .setPassWord(
                            Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin"));

            DwDeviceSet one = dwDeviceSetService.getOne(
                    new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceBaseId, deviceBase.getId()));
            if (one == null) {
                throw new ServiceException(500, "设备尚未进行配置！");
            }

            OpenDoorRequest.InfoDTO infoDTO = new OpenDoorRequest.InfoDTO()
                    .setDeviceID(one.getDeviceId())
                    .setChn(0)
                    .setStatus(1)
                    .setMsg("请通行");

            OpenDoorRequest openDoorRequest = new OpenDoorRequest();
            openDoorRequest.setInfo(infoDTO);
            BaseResponse baseResponse = HQRulesEngine.faceDoorDtoService.openDoor(uri, openDoorRequest, requestHeader);
            if (ObjectUtil.equal(baseResponse.getCode(), 200)) {
                log.info("远程开门成功！");
            } else {
                throw new ServiceException(
                        500,
                        "远程开门 失败信息： code:"
                                + baseResponse.getCode()
                                + " message:  "
                                + Optional.ofNullable(baseResponse.getInfo().getResult())
                                        .orElse("")
                                + " "
                                + Optional.ofNullable(baseResponse.getInfo().getDetail())
                                        .orElse(""));
            }
        } catch (Exception e) {
            throw new ServiceException(500, "远程开门 失败信息：" + ExceptionUtil.getMessage(e));
        }
    }
}
